package org.wak.action
{
	import org.wak.action.modern.ActionControllerModern;
	import org.wak.action.sci.ActionControllerSCI;
	import org.wak.action.scumm.ActionControllerScumm;
	import org.wak.dialog.DialogManager;
	import org.wak.dialog.event.PuzzleActionEvent;
	import org.wak.gui.GuiManager;
	import org.wak.gui.events.GuiEvent;
	import org.wak.main.AdventureStyle;
	import org.wak.main.PuzzleControllerBase;
	import org.wak.scene.SceneManager;
	import org.wak.scene.events.SceneEvent;
	import org.wak.utils.ArrayIterator;
	import org.wak.utils.IIterator;
	
	/**
	 * This class is the core of the player's interaction.
	 * This coordinates the routing of the actions events and controls 
	 * the Scenes and Gui. 
	 * 
	 */	
	public class ActionsManager
	{
		// the adventure style of the game
		private var mAdventureStyle:String = "";
		
		// a local reference to the SceneManager
		private var mSceneMngr:SceneManager = null;
		
		// a local reference to the Gui manager.
		private var mGuiMngr:GuiManager = null ;
		
		// a local reference to the Dialog manager.
		private var mDialogMngr:DialogManager = null ;
		
		// the Adventure action controller.
		private var mActionController:IActionController = null ;
		
		// Non asoc Array of PuzzleControllers.
		private var mPuzzleControllerArray:Array = null ;
		
		public function ActionsManager(pAdvStyle:String)
		{
			mAdventureStyle = pAdvStyle ;
			mPuzzleControllerArray = new Array() ;
			
		}
		
		
		/**
		 * Initialize method for the ActionManager 
		 * @param pSceneManager the adventure scene manager.
		 * 
		 */		
		public function Initialize( pSceneManager:SceneManager, pGuiManager:GuiManager, pDialogManager:DialogManager ):void
		{
			mSceneMngr = pSceneManager ;
			mGuiMngr = pGuiManager ;
			mDialogMngr = pDialogManager ;
			// Set the events to listen from the scene manager
			SetSceneMngrEventListeners( mSceneMngr );
			
			// Set the events to listen from the dialogs manager
			SetDialogMngrEventListeners( mDialogMngr );
			
			// Set the events to listen from the gui manager.
			SetGuiMngrEventListeners( mGuiMngr );
			
			// creates the ActionController depending on the adventure style.
			mActionController = CreateActionController(mAdventureStyle);
			mActionController.Initialize() ;
			
		}
		
		private function CreateActionController( pAdventureStyle:String ):IActionController
		{
			var fReturn:IActionController = null ;
			switch(pAdventureStyle)
			{
				case AdventureStyle.ScummStyle:
				fReturn = new ActionControllerScumm();
				break;
				case AdventureStyle.SCIStyle:
				fReturn = new ActionControllerSCI();
				break;
				case AdventureStyle.ModernStyle:
				fReturn = new ActionControllerModern() ;
				break;
			}
			
			return fReturn ;
		}
		
		private function SetDialogMngrEventListeners( pDialogMngr:DialogManager ):void
		{
			pDialogMngr.addEventListener(PuzzleActionEvent.PUZZLE_ACTION_EVENT, OnTopicAction );
		}
		
		private function RemoveDialogMngrEventListeners( pDialogMngr:DialogManager ):void
		{
			pDialogMngr.removeEventListener(PuzzleActionEvent.PUZZLE_ACTION_EVENT, OnTopicAction );
		}
		
		private function SetSceneMngrEventListeners( pSceneMngr:SceneManager ):void
		{
			pSceneMngr.addEventListener(SceneEvent.ENTER_SCENE, OnEnterScene );
			pSceneMngr.addEventListener(SceneEvent.EXIT_SCENE, OnExitScene );
			pSceneMngr.addEventListener(SceneEvent.SCENE_SPACE_CLICK, OnSceneSpaceClick );
			pSceneMngr.addEventListener(SceneEvent.SCENEITEM_CLICK, OnSceneItemClick );
			pSceneMngr.addEventListener(SceneEvent.SCENEITEM_MOUSEOVER, OnSceneItemMouseOver );
			pSceneMngr.addEventListener(SceneEvent.SCENEITEM_MOUSEOUT, OnSceneItemMouseOut );
			
		}
		
		private function RemoveSceneMngrEventListeners( pSceneMngr:SceneManager ):void
		{
			pSceneMngr.removeEventListener(SceneEvent.ENTER_SCENE, OnEnterScene );
			pSceneMngr.removeEventListener(SceneEvent.EXIT_SCENE, OnExitScene );
			pSceneMngr.removeEventListener(SceneEvent.SCENE_SPACE_CLICK, OnSceneSpaceClick );
			pSceneMngr.removeEventListener(SceneEvent.SCENEITEM_CLICK, OnSceneItemClick );
			pSceneMngr.removeEventListener(SceneEvent.SCENEITEM_MOUSEOVER, OnSceneItemMouseOver );
			pSceneMngr.removeEventListener(SceneEvent.SCENEITEM_MOUSEOUT, OnSceneItemMouseOut );
			
		}
		
		private function SetGuiMngrEventListeners( pGuiMngr:GuiManager ):void
		{
			pGuiMngr.addEventListener(GuiEvent.ACTION_SELECTED, OnGuiActionSelected );
			pGuiMngr.addEventListener(GuiEvent.INVENTORY_ITEM_SELECTED, OnGuiInventoryItemSelected );
			pGuiMngr.addEventListener(GuiEvent.INVENTORY_ITEM_OVER, OnGuiInventoryItemOver );
			pGuiMngr.addEventListener(GuiEvent.INVENTORY_ITEM_OUT, OnGuiInventoryItemOut );
			
		}
		
		private function RemoveGuiMngrEventListeners( pGuiMngr:GuiManager ):void
		{
			pGuiMngr.removeEventListener(GuiEvent.ACTION_SELECTED, OnGuiActionSelected );
			pGuiMngr.removeEventListener(GuiEvent.INVENTORY_ITEM_SELECTED, OnGuiInventoryItemSelected );
			pGuiMngr.removeEventListener(GuiEvent.INVENTORY_ITEM_OVER, OnGuiInventoryItemOver );
			pGuiMngr.removeEventListener(GuiEvent.INVENTORY_ITEM_OUT, OnGuiInventoryItemOut );
		}
		
		// Dialog event listeners //
		
		private function OnTopicAction(event:PuzzleActionEvent):void
		{
			//trace("Actions manager OnTopicAction");
			
			CallInPuzzleController(event.methodName);			
		}
		
		protected function CallInPuzzleController(pMethodName:String):void
		{
			var fMethodFound:Boolean = false ;
			for each( var puz:PuzzleControllerBase in mPuzzleControllerArray )
			{
				fMethodFound = puz.hasOwnProperty( pMethodName );
				if(fMethodFound)
				{
					puz[pMethodName]() ;
				}
			}
		}
		
	
		
		// Gui event listeners //
		
		private function OnGuiActionSelected(event:GuiEvent):void
		{
			if(mActionController != null)
				mActionController.OnActionSelected(event);
		}
		
		public function OnGuiInventoryItemSelected(event:GuiEvent):void
		{
			if(mActionController != null)
				mActionController.OnInventoryItemSelected(event);
		}
		
		private function OnGuiInventoryItemOver(event:GuiEvent):void
		{
			if(mActionController != null)
				mActionController.OnInventoryItemOver(event);
		}
		
		private function OnGuiInventoryItemOut(event:GuiEvent):void
		{
			if(mActionController != null)
				mActionController.OnInventoryItemOut(event);
		}
		
		// Scene event listeners //
		
		/**
		 * SCENEITEM_CLICK Event handler 
		 * @param event a SceneEvent .
		 * 
		 */		
		private function OnSceneItemClick( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnSceneItemClick(event);
		}
		
		/**
		 * SCENEITEM_MOUSEOVER Event handler 
		 * @param event a SceneEvent .
		 * 
		 */	
		private function OnSceneItemMouseOver( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnSceneItemMouseOver(event);
		}
		
		/**
		 * SCENEITEM_MOUSEOUT Event handler 
		 * @param event a SceneEvent .
		 * 
		 */	
		private function OnSceneItemMouseOut( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnSceneItemMouseOut(event);
		}
		
		/**
		 * SCENE_SPACE_CLICK Event handler 
		 * @param event a SceneEvent .
		 * 
		 */	
		private function OnSceneSpaceClick( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnSceneSpaceClick(event);
		}
		
		/**
		 * ENTER_SCENE Event handler 
		 * @param event a SceneEvent .
		 * 
		 */	
		private function OnEnterScene( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnEnterScene(event);
		}
		
		/**
		 * EXIT_SCENE Event handler 
		 * @param event a SceneEvent .
		 * 
		 */	
		private function OnExitScene( event:SceneEvent ):void
		{
			//trace("ActionsManager: "+event);
			if(mActionController != null)
				mActionController.OnExitScene(event);
		}
		
		/**
		 * Add a new  PuzzleControllerBase to the actions management.
		 * @param pPc
		 * 
		 */		
		public function AddPuzzleController( pPc:PuzzleControllerBase ):void
		{
			mPuzzleControllerArray.push(pPc);
		}
		
		/**
		 * Remove a PuzzleControllerBase from the actions management.
		 * @param pPc
		 * 
		 */		
		public function RemovePuzzleController( pPc:PuzzleControllerBase ):void
		{
			var fIx:int = mPuzzleControllerArray.indexOf(pPc);
			if( fIx >= 0)
			{
				mPuzzleControllerArray.splice(fIx,1);
			}
		}
		
		/**
		 *  
		 * @return IIterator to iterate through the puzzle controllers array. 
		 * 
		 */		
		public function GetPuzzleControllers():IIterator
		{
			return new ArrayIterator( mPuzzleControllerArray );
		}
		
		public function EndOfAction():void
		{
			mActionController.EndOfAction() ;
			
		}
		
		

	}
}